Flutter TextureAndroidViewController

Virtual displays 模式下,TextureAndroidViewController 是对《Flutter AndroidViewController》的实现。在本文中分析 TextureAndroidViewController 类的实现原理。


关键属性

/// 纹理 id
int? _textureId;

/// 记录视图大小,原生视图在 Flutter 侧的大小
late Size _size;

setSize 设置大小

Flutter 侧的映射组件 AndroidView 和被嵌入的原生视图 PlatformView,他们位于 Flutter/Android 两套布局系统中,因此需要一个相互同步的过程。

setSize 方法是当 Flutter 侧的组件大小变化时,通知 PlatformView 进行相应大小调整:

@override
Future<void> setSize(Size size) async {
  // ...
  // 首次分配大小是创建原生视图
  if (_state == _AndroidViewState.waitingForSize) {
    _size = size;
    return create();
  }

  await SystemChannels.platform_views.invokeMethod<void>('resize', <String, dynamic>{
    'id': viewId,
    'width': size.width,
    'height': size.height,
  });
}

其中:通过 SystemChannels.platform_views channel 向原生侧发送 resize 事件。

其中有一个分支语句,在首次分配大小时,创建原生视图。这是原生视图的创建时机,非常关键。这也可以理解,因为只有 Flutter 首次分配大小时,我们才知道这个组件的大小,有了大小才能够触发原生侧布局。

setSize 被谁调用呢?被《Flutter RenderAndroidView#performResize》,performResize 是 RenderObject 的回调方法,由 Flutter 布局系统通知视图调整大小。因此,我们经由 RenderAndroidView,再回到这里,通知原生侧调整大小。


_sendCreateMessage 发送创建消息

这个消息将触发原生侧开始创建原生视图,也是对 Flutter AndroidViewController 中抽象接口的实现:

@override
Future<void> _sendCreateMessage() async {
  //...

  // 封装一个消息
  final Map<String, dynamic> args = <String, dynamic>{
    'id': viewId,
    'viewType': _viewType,
    'width': _size.width,
    'height': _size.height,
    'direction': AndroidViewController._getAndroidDirection(_layoutDirection),
  };
  // 封装传入参数
  if (_creationParams != null) {
    final ByteData paramsByteData = _creationParamsCodec!.encodeMessage(_creationParams)!;
    args['params'] = Uint8List.view(
      paramsByteData.buffer,
      0,
      paramsByteData.lengthInBytes,
    );
  }
  // 通过 Channel 触发原生侧创建,原生侧创建好后,返回 Texture ID
  _textureId = await SystemChannels.platform_views.invokeMethod<int>('create', args);
}

这个逻辑非常重要,他是原生视图侧创建纹理的桥梁。


_sendDisposeMessage 发送释放销毁

也是对 Flutter AndroidViewController 中抽象接口的实现:

@override
Future<void> _sendDisposeMessage() {
  return SystemChannels
      .platform_views.invokeMethod<void>('dispose', <String, dynamic>{
    'id': viewId,
    'hybrid': false,
  });
}

注意,其中有一个 hybrid 参数,为 false 表示是 Virtual displays 模式下。

Note

全局搜索以下 'hybrid': true, 即可找到 Hybrid composition 模式下的消息通信,位于 SurfaceAndroidViewController 类中,这部分实现,将在后续分析 Hybrid composition 模式时再进行梳理。


本文作者:Maeiee

本文链接:Flutter TextureAndroidViewController

版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!


喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!